package com.szamc.tableroundapi.service;

import com.szamc.tableroundapi.model.Common.UnitOption;
import com.szamc.tableroundapi.model.RecursionTable.*;
import io.swagger.models.auth.In;
import lombok.var;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class TreeTableApiService {

    private static Object[] RowOptions;
    private static Object[] ColumnOptions;
    private static double DivideNumber;
    private static int Precision;
    private static ArrayList<ArrayList<Double>> TableList;
    private static final List<TreeItem> RowTreeList = new ArrayList<TreeItem>();//clear
    private static final List<TreeItem> AllRowTreeList = new ArrayList<TreeItem>();//clear
    private static final List<ColumnGroupItem> ColumnGroupList = new ArrayList<ColumnGroupItem>();//clear
    private static final List<ColumnGroupItem> AllColumnGroupList = new ArrayList<ColumnGroupItem>();//clear
    private static List<GroupIndexPath> GroupIndexPathList = new ArrayList<GroupIndexPath>();
    private static ArrayList<RecursionTableFormatData> RecursionTableFormatDataList = new ArrayList<RecursionTableFormatData>();
    private static ArrayList<RTGroupData> RTGroupDataList = new ArrayList<RTGroupData>();
    private static ArrayList<String> AddList = new ArrayList<String>();

    public ArrayList<ArrayList<Double>> GetRoundTable(
            ArrayList<ArrayList<Double>> _tableList,
            Object[] _rowOptions,
            Object[] _columnOptions,
            UnitOption _unitOption
            ) throws NoSuchFieldException, IllegalAccessException {
        ClearGlobalValue();//清理全局变量
        RowOptions = _rowOptions;
        ColumnOptions = _columnOptions;//默认ColumnTreeList不存在多级
        TableList = _tableList;
        DivideNumber = _unitOption.divideNumber;//除以多少
        Precision = _unitOption.precision;//小数点后多少位
        CreateRowTreeList(RowOptions, 0, new ArrayList<>());
        CreateColumnGroupList(ColumnOptions, 0, new ArrayList<>());
        GroupIndexPathList = GetGroupIndexPathList();
        RTGroupDataList = GetGroupDataList(GroupIndexPathList, null);
        RecursionTableFormatDataList = GetForMatDataList();
        AttachGroupInfo(RTGroupDataList);
        Double _sum = GetAllSum();
        AttachGroupAdjustSum(RTGroupDataList, (double) Math.round(_sum));
        CreateAddList(RTGroupDataList);
        RoundForMatData();
        var _result = GetResultList();
        AddSumRow(_result);
        AddSumColumn(_result);
        return _result;

    }

    private void ClearGlobalValue() {
        RowTreeList.clear();
        AllRowTreeList.clear();
        ColumnGroupList.clear();
        AllColumnGroupList.clear();
        GroupIndexPathList.clear();
        RecursionTableFormatDataList.clear();
        RTGroupDataList.clear();
        AddList.clear();
    }

    //按字段展开
    private ArrayList<RecursionTableFormatData> GetForMatDataList() throws NoSuchFieldException, IllegalAccessException {
        var recursionTableFormatDataList = new ArrayList<RecursionTableFormatData>();
        for (int i = 0; i < RowTreeList.size(); i++) {
            for (int j = 0; j < ColumnGroupList.size(); j++) {
                var _valueType = RowTreeList.get(i).getValue();
                var _value = GetProcessValue(TableList.get(j).get(i));
                var _recursionTableFormatData = new RecursionTableFormatData(
                        i + "_" + j,
                        i,
                        j,
                        _valueType==1?_value:-_value,//value
                        RowTreeList.get(i).getGroupIndexPathList(),
                        ColumnGroupList.get(j).getGroupIndex(),
                        _valueType

                );
                recursionTableFormatDataList.add(_recursionTableFormatData);
            }
        }
        return recursionTableFormatDataList;
    }
    private double GetProcessValue(double OriginalValue){
        return  (OriginalValue/DivideNumber)*Math.pow(10, Precision);
    }
    //构造RowTreeList，存入全局变量，Tree按深度优先遍历
    private void CreateRowTreeList(Object[] arr, int level, List<Integer> path) {
        if (arr == null) return;
        for (int i = 0; i < arr.length; i++) {
            Object item = arr[i];
            // 复制当前路径并追加当前索引
            List<Integer> newPath = new ArrayList<>(path);
            newPath.add(i);
            if (item instanceof ArrayList) {
                ArrayList<?> _item = (ArrayList<?>) item;
                // 递归调用，层级加1
                CreateRowTreeList(_item.toArray(), level + 1, newPath);
            } else {
                if (item != null) {
                    // 打印当前层级和路径
                    //newPath.remove(newPath.size() - 1);
                    String _id = String.join("_", newPath.stream().map(Object::toString).collect(Collectors.toList()));
                    if (Objects.equals(item.toString(), "1")
                            || Objects.equals(item.toString(), "-1")
                    ) {
                        RowTreeList.add(new TreeItem(_id, level, newPath, RowTreeList.size(), (int) item));
                    }
                    AllRowTreeList.add(new TreeItem(_id, level, newPath, AllRowTreeList.size(), (int) item));
                }
            }
        }
    }

    //构造ColumnGroupList，存入全局变量，Tree按深度优先遍历
    private void CreateColumnGroupList(Object[] arr, int level, List<Integer> path) {
        if (arr == null) return;
        for (int i = 0; i < arr.length; i++) {
            Object item = arr[i];
            // 复制当前路径并追加当前索引
            List<Integer> newPath = new ArrayList<>(path);
            newPath.add(i);
            if (item instanceof ArrayList) {
                ArrayList<?> _item = (ArrayList<?>) item;
                // 递归调用，层级加1
                CreateColumnGroupList(_item.toArray(), level + 1, newPath);
            } else {
                if (item != null) {
                    String _id = String.join("_", newPath.stream().map(Object::toString).collect(Collectors.toList()));
                    Integer _groupIndex = newPath.get(0);
                    if (Objects.equals(item.toString(), "1")
                            || Objects.equals(item.toString(), "-1")
                    ) {
                        ColumnGroupList.add(new ColumnGroupItem(_id, ColumnGroupList.size(), _groupIndex, (int) item,newPath));
                    }

                    AllColumnGroupList.add(new ColumnGroupItem(_id, AllColumnGroupList.size(), _groupIndex, (int) item,newPath));
                }
            }
        }
    }

    private List<GroupIndexPath> GetGroupIndexPathList() {
        var rtList = new ArrayList<String>();
        var cList = new ArrayList<Integer>();
        var resultList = new ArrayList<GroupIndexPath>();
        for (TreeItem treeItem : RowTreeList) {
            List<Integer> rpathList = treeItem.getGroupIndexPathList();
            var _traversePathList = GetTraversePathList(rpathList);
            for (String s : _traversePathList) {
                if (!rtList.contains(s)) {
                    rtList.add(s);
                }
            }
        }

        for (ColumnGroupItem columnGroupItem : ColumnGroupList) {
            if (!cList.contains(columnGroupItem.getGroupIndex())) {
                cList.add(columnGroupItem.getGroupIndex());
            }
        }

        for (String s : rtList) {
            for (Integer integer : cList) {
                var _groupIndexPath = new GroupIndexPath(
                        s + "-" + integer,
                        GetPid(s, integer)
                );
                resultList.add(_groupIndexPath);
            }
        }
        return resultList;
    }

    //获取全路径
    private List<String> GetTraversePathList(List<Integer> list) {
        String _lastPath = "";
        List<String> resultList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            String resultItem = _lastPath + (i == 0 ? "" : "_") + list.get(i);
            resultList.add(resultItem);
            _lastPath = resultItem;
        }
        return resultList;
    }

    //获取Pid
    private String GetPid(String rt, Integer c) {
        int lastIndex = rt.lastIndexOf("_");
        if (lastIndex != -1) {
            return rt.substring(0, lastIndex) + "-" + c;
        }
        return null;
    }

    private ArrayList<RTGroupData> GetGroupDataList(List<GroupIndexPath> groupIndexPathList, String parentId) {
        ArrayList<RTGroupData> trees = new ArrayList<RTGroupData>();
        //获取到所有parentCode的子节点
        for (GroupIndexPath item : groupIndexPathList) {
            boolean IsEquals = false;
            if (parentId == null) {
                if (item.getPid() == null) {
                    IsEquals = true;
                }
            } else if (parentId.equals(item.getPid())) {
                IsEquals = true;
            }
            if (IsEquals) {
                var _treeItem = new RTGroupData(item.getId());
                trees.add(_treeItem);
                //递归遍历该子节点的子节点列表
                _treeItem.setChildren(GetGroupDataList(groupIndexPathList, item.getId()));
            }
        }
        return trees;
    }

    //附加ids和组合计信息
    private void AttachGroupInfo(List<RTGroupData> rootList) {
        if (rootList == null) return;
        for (RTGroupData root : rootList) {
            // 处理当前节点
            var ids = GetIdsByGroupId(root.getId());
            root.setIds(ids);
            var _sum = GetSumByIds(ids);
            root.setSum(_sum);
            root.setFlootSum(Math.floor(_sum));
            root.setDecimalPart(_sum - Math.floor(_sum));
            if (root.getChildren() != null) {
                AttachGroupInfo(root.getChildren());
            }
        }
    }

    private List<String> GetIdsByGroupId(String groupId) {
        String[] parts = groupId.split("-");
        String RPart = parts[0];
        var _length = RPart.split("_").length;
        String Cpart = parts[1];
        var result = RecursionTableFormatDataList.stream()
                .filter(p ->
                        listToString(p.getRowGroupIndexPathList(), _length).equals(RPart)
                                &&
                                p.getColumnGroupIndex().toString().equals(Cpart))
                .map(RecursionTableFormatData::getId)
                .collect(Collectors.toList());
        return result;
    }

    private static String listToString(List<Integer> list, Integer length) {
        StringBuilder sb = new StringBuilder();
        if (list.size() > length) {
            list = list.subList(0, length);
        }
        for (int i = 0; i < list.size(); i++) {
            sb.append(list.get(i));
            if (i < list.size() - 1) {
                sb.append("_");
            }
        }
        return sb.toString();
    }

    private Double GetSumByIds(List<String> ids) {
        var valueList = RecursionTableFormatDataList.stream().filter(
                        p -> ids.contains(p.getId()))
                .map(RecursionTableFormatData::getValue)
                .collect(Collectors.toList());
        double sum = 0.00;
        for (Double aDouble : valueList) {
            sum = sum + aDouble;
        }
        return sum;
    }

    //计算分组舍位平衡
    private void AttachGroupAdjustSum(List<RTGroupData> rootList, Double roundSum) {
        if (rootList == null) return;
        if (rootList.isEmpty()) return;
        double AllFlootSum = 0;
        for (RTGroupData rtGroupData : rootList) {
            AllFlootSum = AllFlootSum + rtGroupData.getFlootSum();
        }
        double addCount = roundSum - AllFlootSum;//计算出要加几
        int IntAddCount = (int) Math.round(addCount);
        List<RTGroupData> copyRootList = new ArrayList<>(rootList);//排序
        copyRootList.sort(Comparator.comparing(RTGroupData::getDecimalPart).reversed());
        List<String> _addGroupIds = copyRootList.subList(0, IntAddCount).stream().map(RTGroupData::getId).collect(Collectors.toList());
        for (RTGroupData rtGroupData : rootList) {
            var floorSum = rtGroupData.getFlootSum();
            rtGroupData.setAdjustSum(rtGroupData.getFlootSum());
            if (_addGroupIds.contains(rtGroupData.getId())) {
                rtGroupData.setAdjustSum(floorSum + 1);
            } else {
                rtGroupData.setAdjustSum(floorSum);
            }
            //下面是递归调用
            if (rtGroupData.getChildren() != null) {
                var _roundSum = rtGroupData.getAdjustSum();
                AttachGroupAdjustSum(rtGroupData.getChildren(), _roundSum);
            }
        }
    }

    //找出需要加1的ID
    private void CreateAddList(List<RTGroupData> GroupDataList) {
        if (GroupDataList == null) return;
        for (RTGroupData rtGroupData : GroupDataList) {
            if (rtGroupData.getChildren() != null
                    && !rtGroupData.getChildren().isEmpty()) {
                CreateAddList(rtGroupData.getChildren());
            } else {
                GetAddList(rtGroupData.getIds(), rtGroupData.getAdjustSum());
            }
        }
    }

    //往全局变量里面加
    private void GetAddList(List<String> Ids, double adjustSum) {
        double AllFlootSum = 0;
        for (int i = 0; i < Ids.size(); i++) {
            int finalI = i;
            var _value = RecursionTableFormatDataList.stream()
                    .filter(p -> p.getId().equals(Ids.get(finalI)))
                    .findFirst().get().getFloorValue();
            AllFlootSum = AllFlootSum + _value;
        }
        //计算出要加几
        double addCount = adjustSum - AllFlootSum;
        int IntAddCount = (int) Math.round(addCount);
        var _dataList = RecursionTableFormatDataList.stream()
                .filter(p -> Ids.contains(p.getId()))
                .collect(Collectors.toList());
        _dataList.sort(Comparator.comparing(RecursionTableFormatData::getDecimalPart).reversed());//排序
        for (int i = 0; i < IntAddCount; i++) {
            var _id = _dataList.get(i).getId();
            AddList.add(_id);
        }
    }

    private Double GetAllSum() {
        double sum = 0.00;
        for (int i = 0; i < RecursionTableFormatDataList.size(); i++) {
            sum = sum + RecursionTableFormatDataList.get(i).getValue();
        }
        return sum;
    }

    private void RoundForMatData() {
        for (int i = 0; i < RecursionTableFormatDataList.size(); i++) {
            int finalI = i;
            var _value = RecursionTableFormatDataList.get(finalI).getFloorValue();
            if (RecursionTableFormatDataList.stream().anyMatch(p -> AddList.contains(
                    RecursionTableFormatDataList.get(finalI).getId()
            ))) {
                RecursionTableFormatDataList.get(i).setAdjustValue(_value + 1);

            } else {
                RecursionTableFormatDataList.get(i).setAdjustValue(_value);
            }
        }
    }

    private ArrayList<ArrayList<Double>> GetResultList() {
        var resultList = new ArrayList<ArrayList<Double>>();
        for (int i = 0; i < ColumnGroupList.size(); i++) {//6行
            var _TempList = new ArrayList<Double>();
            for (int j = 0; j < RowTreeList.size(); j++) {
                int finalI = i;
                int finalJ = j;
                var _value = RecursionTableFormatDataList.stream()
                        .filter(p -> p.getColumnIndex() == finalI && p.getRowIndex() == finalJ)
                        .findFirst().get().getAdjustValue();
                _TempList.add(GetOriginalValue(_value,RowTreeList.get(j).getValue()));
            }
            resultList.add(_TempList);
        }
        return resultList;
    }
    private double GetOriginalValue(double ProcessValue,int fieldType){
        double result = round(ProcessValue/Math.pow(10, Precision), Precision);
        return fieldType==1?result:-result;
    }
    private static double round(double value, int places) {
        BigDecimal bd = BigDecimal.valueOf(value);
        bd = bd.setScale(places, RoundingMode.HALF_UP);
        return bd.doubleValue();
    }
    private List<Integer> GetTreeItemIndexList(List<Integer> groupIndexPathList) {
        int _length = groupIndexPathList.size();
        var _treeItemIds = RowTreeList.stream()
                .filter(p -> GetSubList(p.getGroupIndexPathList(), _length).equals(groupIndexPathList))
                .map(TreeItem::getIndex)
                .collect(Collectors.toList());
        return _treeItemIds;
    }

    private List<Integer> GetSubList(List<Integer> GroupIndexPathList, int length) {
        if (length > GroupIndexPathList.size()) {
            return new ArrayList<Integer>();
        } else {
            var a = GroupIndexPathList.subList(0, length);
            return GroupIndexPathList.subList(0, length);
        }
    }

    private List<Integer> GetColumnIndexList(List<Integer> groupIndexPathList) {
        List<Integer> columnIndexList = new ArrayList<>();
        if(groupIndexPathList.size() == 0){
            columnIndexList = ColumnGroupList.stream()
                    .map(ColumnGroupItem::getIndex)
                    .collect(Collectors.toList());
        }
        else{
            columnIndexList = ColumnGroupList.stream().filter(p -> p.getGroupIndexPathList().get(0) == groupIndexPathList.get(0))
                    .map(ColumnGroupItem::getIndex)
                    .collect(Collectors.toList());
        }

        return columnIndexList;
    }

    private void AddSumRow(ArrayList<ArrayList<Double>> resultList) {
        var copyResultList = deepCopyList(resultList);
        var _sumRowList = AllRowTreeList.stream().filter(p -> p.getValue() == 2).collect(Collectors.toList());
        for (int i = 0; i < _sumRowList.size(); i++) {
            var _treeItemIndexList = GetTreeItemIndexList(_sumRowList.get(i).getGroupIndexPathList());

            for (int j = 0; j < copyResultList.size(); j++) {//一行一行来
                var _copyRowItem = copyResultList.get(j);//一行
                var _rowSum = 0.00;

                for (int k = 0; k < _treeItemIndexList.size(); k++) {
                    int _index = _treeItemIndexList.get(k);
                    int _valueType = RowTreeList.get(_index).getValue();
                    double _value = _valueType==1?_copyRowItem.get(_index):-_copyRowItem.get(_index);
                    _rowSum = _rowSum + _value;
                }
                var _rowItem = resultList.get(j);//一行
                _rowItem.add(_sumRowList.get(i).getIndex(), round(_rowSum, Precision));
            }
        }
    }
    private static List<List<Double>> deepCopyList(ArrayList<ArrayList<Double>> originalList) {
        List<List<Double>> newList = new ArrayList<>();
        for (List<Double> innerList : originalList) {
            List<Double> newInnerList = new ArrayList<>(innerList);
            newList.add(newInnerList);
        }
        return newList;
    }
    private void AddSumColumn(ArrayList<ArrayList<Double>> resultList) {
        var copyResultList = deepCopyList(resultList);
        var _sumColumnList = AllColumnGroupList.stream().filter(p -> p.getValue() == 2).collect(Collectors.toList());
        for (int i = 0; i < _sumColumnList.size(); i++) {
            var sumRowList = new ArrayList<Double>();
            for (int j = 0; j < AllRowTreeList.size(); j++) {//每一列
                var _columnIndexList = GetColumnIndexList(_sumColumnList.get(i).getGroupIndexPathList());//哪几行
                var sum = 0.00;
                for (int k = 0; k < _columnIndexList.size(); k++) {//每一行
                    var _value = copyResultList.get(_columnIndexList.get(k)).get(j);
                    sum = sum + _value;
                }
                sumRowList.add(round(sum, Precision));
            }
            resultList.add(_sumColumnList.get(i).getIndex(),sumRowList);
        }
    }

}
